package com.example.mydemoproject.config.exception;

import com.example.mydemoproject.model.response.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingRequestHeaderException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;

import java.util.Set;

/**
 * @description: 异常处理器
 * @author: LiuZhiYong
 * @create: 2021-12-02
 **/
@RestControllerAdvice
@Slf4j
public class MyExceptionHandler {

    /**
     * 处理自定义异常ServiceException
     */
    @ExceptionHandler(ServiceException.class)
    public Result<Object> handleBusinessException(ServiceException e) {
        log.error(e.getMessage(), e);
        return Result.error("网络开小差了!");
    }

    /**
     * 处理自定义异常BusinessException
     */
    @ExceptionHandler(BusinessException.class)
    public Result<Object> handleBusinessException(BusinessException e) {
		log.error(e.getMessage(), e);
    	if (e.getCode() != null) {
			return Result.error(e.getCode(), e.getMessage());
        } else {
			return Result.error(e.getMessage());
        }
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public Result<Object> handlerNoFoundException(Exception e) {
        log.error(e.getMessage(), e);
        return Result.error(404, "路径不存在，请检查路径是否正确");
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public Result<Object> handleDuplicateKeyException(DuplicateKeyException e) {
        log.error(e.getMessage(), e);
        return Result.error("数据库中已存在该记录");
    }

    //@ExceptionHandler({UnauthorizedException.class, AuthorizationException.class})
    //public Result<Object> handleAuthorizationException(AuthorizationException e){
    //	log.error(e.getMessage(), e);
    //	return Result.noauth("没有权限，请联系管理员授权");
    //}

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result<Object> HttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        StringBuffer sb = new StringBuffer();
        sb.append("不支持");
        sb.append(e.getMethod());
        sb.append("请求方法，");
        sb.append("支持以下");
        String[] methods = e.getSupportedMethods();
        if (methods != null) {
            for (String str : methods) {
                sb.append(str);
                sb.append("、");
            }
        }
        log.error(sb.toString(), e);
        return Result.error(405, sb.toString());
    }

    /**
     * spring默认上传大小100MB 超出大小捕获异常MaxUploadSizeExceededException
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public Result<Object> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
        log.error(e.getMessage(), e);
        return Result.error("文件大小超出10MB限制, 请压缩或降低文件质量! ");
    }

    @ExceptionHandler(DataIntegrityViolationException.class)
    public Result<Object> handleDataIntegrityViolationException(DataIntegrityViolationException e) {
        log.error(e.getMessage(), e);
        return Result.error("网络波动,数据库连接异常,请联系管理员");
    }

    /**
     * 处理valid注解参数校验异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<Object> handleValidException(MethodArgumentNotValidException e) {
        log.error(e.getMessage(), e);
        BindingResult bindingResult = e.getBindingResult();
        String str = "信息填写错误:";
        if (bindingResult.hasErrors()) {
            List<ObjectError> errors = bindingResult.getAllErrors();
			FieldError fieldError = (FieldError) errors.get(0);
			str = str + fieldError.getField() + "字段," + fieldError.getDefaultMessage();
        }
        return Result.error(str);
    }

    /**
     * 请求缺失必传参数
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public Result<Object> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        log.error(e.getMessage(), e);
        String parameterName = e.getParameterName();
        String parameterType = e.getParameterType();
        return Result.error("缺少必传参数：" + parameterName + "，类型为：" + parameterType);
    }

    /**
     * 请求缺失必传参数
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public Result<Object> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
        log.error(e.getMessage(), e);
        String name = e.getName();
        Class<?> requiredType = e.getRequiredType();
        String localizedMessage = e.getLocalizedMessage();
        return Result.error("参数" + name + "类型错误,需要的类型为：" + requiredType.toString() + "，信息:" + localizedMessage);
    }

    /**
     * javax.validation.constraints校验注解异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result<Object> handleConstraintViolationException(ConstraintViolationException e) {
        log.error(e.getMessage(), e);
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        String str = "";
        for (ConstraintViolation<?> constraintViolation : constraintViolations) {
            String message = constraintViolation.getMessage();
            str = str + message + " ";
        }
        return Result.error(str);
    }

	@ExceptionHandler(MissingRequestHeaderException.class)
	public Result throwCustomException(MissingRequestHeaderException missingRequestHeaderException){
		log.info("missingRequestHeaderException------:{}",missingRequestHeaderException);
		Result Result = new Result();
		Result.setCode(410);
		Result.setSuccess(false);
		Result.setMessage(missingRequestHeaderException.getMessage());
		return Result;
	}

    @ExceptionHandler(Exception.class)
    public Result<Object> handleException(Exception e) {
        log.error(e.getMessage(), e);
        return Result.error("网络开小差了!");
    }

}
